﻿<html>
<head>
<meta charset="utf-8" />
<title>跳棋</title>
<style>
body{
    margin:0px;
}
.full{
    width: 100%;
    height: 100%;    
}
</style>
<script>

/*
屏幕坐标系 
 ___ x
|
y

竖直方向画布坐标系
 ___ x
|
y

水平方向画布坐标系
y___
    |
    x


棋盘坐标系
_____ x
\
 \
  y

-3 -2 -1 1 2 3 分别代表玩家

players数据:
orgin: -3~3 //出发位置
target: 目标位置数组 10个
finish: 已经走完

pieces数据:
所属玩家代号

jumping数据:
x: 坐标
y: 坐标
steps: 经过坐标数组

棋子位置状态:
空
有子
被选择
跳过

*/


let colors = {};

colors[0] = "#e0e0e0";
colors[1] = "#ff0000";
colors[2] = "#ff00ff";
colors[3] = "#00ffff";
colors[4] = "#0000ff";
colors[5] = "#00ff00";
colors[6] = "#ffff00";

//重置所有棋子状态
function reset(state){
    state.pieces = {};
    for (let x = -8; x <= 8; x++) {
        state.pieces[x] = {};
    }
    state.players = {}; 
    state.step = 0; // 
    state.jumping = undefined;   
    state.closing = undefined;
    state.moving = undefined; 
    joinPlayer(state, 4);
    joinPlayer(state, 1);
}

//遍历棋盘每个点  cb(x, y, type）
function forEachBoardPos(cb){
    for (let x = -8; x <= 8; x++) {
        for (let y = -8; y <= 8; y++) {
            let type = checkBoardPos(x, y);
            if(type)cb(x, y, type);        
        }
    }     
}

//计算两点之间的棋子个数
function countPieceInLine(state, sx, sy, tx, ty){
    let count = 0;
    let dy = ty - sy;
    let dx = tx - sx;
    let absx = Math.abs(dx);
    let absy = Math.abs(dy);    
    if(sx == tx){        
        if(absy <= 1)return 0;
        let d = dy > 0?1:-1;
        for (let i = sy + d; i != ty; i += d) {
            if(getPieceOwner(state, sx, i)){
                count ++;
            }            
        }
        return count;
    }
    if(sy == ty){        
        if(absx <= 1)return 0;
        let d = dx > 0?1:-1;
        for (let i = sx + d; i != tx; i += d) {
            if(getPieceOwner(state, i, sy)){
                count ++;
            }            
        }
        return count;
    }
    if(dy == 0 - dx){
        if(absx <= 1)return 0;
        let d = dx > 0?1:-1;
        let d2 = dy > 0?1:-1;
        let tempy = sy + d2;
        for (let tempx = sx + d; tempx != tx; tempx += d) {
            if(getPieceOwner(state, tempx, tempy)){
                count ++;
            } 
            tempy += d2;           
        } 
        return count;       
    }
    return 0;
}

//获取两点中间坐标
function getCenterPos(sx, sy, tx, ty){
    let dy = ty - sy;
    let dx = tx - sx;
    let absx = Math.abs(dx);
    let absy = Math.abs(dy);
    if(sx == tx){
        if(absy % 2)return undefined;
        let y = (sy + ty) / 2;
        return {x:sx, y:y}
    }
    if(sy == ty){
        if(absx % 2)return undefined;
        let x = (sx + tx) / 2;
        return {x:x, y:sy}
    } 
    if(dy == 0 - dx){
        if(absx <= 1)return 0;
        if(absx % 2)return undefined;
        let x = (sx + tx) / 2;
        let y = (sy + ty) / 2;
        return {x:x, y:y}
    }  
    return undefined;
}


//当前棋子能否跳到指定位置
function canJump(state, x, y){    
    let srcx = state.jumping.x;
    let srcy = state.jumping.y;
    if(state.jumping.steps.length){
        let laststep = state.jumping.steps[state.jumping.steps.length - 1];
        srcx = laststep.x;
        srcy = laststep.y;
    }
    let cpos = getCenterPos(srcx, srcy, x, y);
    if(!cpos)return false;
    if(!getPieceOwner(state, cpos.x, cpos.y))return false;
    let count = countPieceInLine(state, srcx, srcy, x, y);   
    if(count == 1)return true; 
    return false;
}   

//当前棋子能否移动到指定位置
function canMove(state, x, y){
    let srcx = state.jumping.x;
    let srcy = state.jumping.y;
    let dx = x - srcx;
    let dy = y - srcy;
    if(srcx == x && Math.abs(dy) == 1)return true;
    if(srcy == y && Math.abs(dx) == 1)return true;
    if(Math.abs(dx) == 1 && dx == 0 - dy)return true;
    return false;
}


function getPlayerCount(state){
    let count = 0;
    for (const key in state.players) {
        count ++;
    }
    return count;
}

//获取指定位置棋子状态 null=无 {owner:number, color:string, selected:bool, jumped:bool}
function getPieceBlock(state, x, y){
    let stat = {};
    let owner = getPieceOwner(state, x, y);
    if(owner){
        stat.owner = owner;
        stat.color = colors[owner];
        if(state.jumping && state.jumping.x == x && state.jumping.y == y){
            stat.selected = true;
        }
        return stat;
    }
    if(state.jumping){
        for (let i = 0; i < state.jumping.steps.length; i++) {
            let step = state.jumping.steps[i];
            if(step.x == x && step.y == y){
                stat.color = colors[state.step];
                stat.jumped = true;
                return stat;
            }
        }
    }
    return undefined;    
}

//获取指定位置棋子所属
function getPieceOwner(state, x, y){
    if(!state.pieces[x])return undefined;
    return state.pieces[x][y];
}

//删除指定位置棋子
function removePiece(state, x, y){
    if(!state.pieces[x])return undefined;
    state.pieces[x][y] = undefined;
}

//设置指定位置棋子所属
function setPieceOwner(state, x, y, owner){
    if(!state.pieces[x]){
        state.pieces[x] = {};
    }
    state.pieces[x][y] = owner;
}

//玩家加入 
function joinPlayer(state, orgin){
    let player = {};
    player.orgin = orgin;
    player.target = [];
    forEachBoardPos((x, y, type)=>{
        if(type == (0 - orgin)){
            let pos = {x:x,y:y};
            player.target.push(pos);
        }else if(type == orgin){
            setPieceOwner(state, x,y,type);
        }
    });
    state.players[orgin] = player;
}

//玩家离开
function removePlayer(state, orgin){
    forEachBoardPos((x, y, type)=>{
        let o = getPieceOwner(state, x, y);
        if(o == orgin){
            removePiece(state, x, y);
        }
    });
    state.players[orgin] = undefined;
    if(state.step)nextStep(state);
    let count = 0;
    for (const key in state.players) {
        if (state.players[key]) {
            count++;
        }
    }
    if(count == 0){
        state.step = 0;
    }
}

//下一个玩家走
function nextStep(state){
    state.jumping = undefined;
    if(getPlayerCount(state) == 0)return;
    for (let i = 0; i <= 6; i++) {
        state.step ++;
        if(state.step == 0)state.step = 1;
        if(state.step > 6) state.step = 1;
        if(state.players[state.step]){
            if(state.players[state.step].finish)continue;
            return;
        }
    }
}

//棋盘坐标验证，范围外返回0，中心区域返回7，边缘区域返回 1 2 3 4 5 6
function checkBoardPos(x, y){
    if(y < -4){
        if(x > 4 || (x + y) < -4)return 0;
        return 4;
    }
    if(y > 4){
        if(x < -4 || (x + y) > 4)return 0;
        return 1;
    } 
    if(x > 4){
        if(y < -4 || (x + y) > 4)return 0;
        return 5;
    }  
    if(x < -4){
        if(y > 4 || (x + y) < -4)return 0;
        return 2;
    }   
    if((x + y) > 4)return 6;
    if((x + y) < -4)return 3;
    return 7;
}

//检查是否结束
function checkFinish(state, playerid){
    let player = state.players[playerid];
    if(!player)return;
    for (let i = 0; i < player.target.length; i++) {
        let pos = player.target[i];
        let owner = getPieceOwner(state, pos.x, pos.y);
        if(owner != player){
            return;
        }
    }
    state.players[playerid].finish = true;
}


//窗口坐标在棋盘边缘  0表示在棋盘内 -1 1 -2 2 
function checkEdgePos(state, x, y){
    let cpos = posWinToCanvas(state, x, y);
    if(cpos.x < 0 && cpos.x < (0 - state.board.width / 2)){
        return -1;
    }
    if(cpos.y < 0 && cpos.y < (0 - state.board.height / 2)){
        return -2;
    }
    if(cpos.x > 0 && cpos.x > (state.board.width / 2)){
        return 1;
    }
    if(cpos.y > 0 && cpos.y > (state.board.height / 2)){
        return 2;
    }   
    return 0;     
}


//棋盘坐标转画布坐标
function posBoardToCanvas(state, x, y){
    let pos = {};
    pos.x = x * state.board.gridWidth + y * state.board.gridWidth / 2;
    pos.y = y * state.board.gridWidth * 0.866;
    return pos;
}

//窗口坐标转画布坐标
function posWinToCanvas(state, x, y){
    let pos = {};
    if(!state.rotate){
        pos.x = x - state.canvas.width / 2;
        pos.y = y - state.canvas.height / 2;
    }else{  //y越大x越大 x越小y越大      
        pos.x = y - state.canvas.height / 2;
        pos.y = state.canvas.width / 2 - x;        
    }
    return pos;
}

//画布坐标转棋盘坐标
function posWinToBoard(state, x, y){
    let pos = {}; 
    let cpos = posWinToCanvas(state, x, y); 
    pos.y = Math.round(cpos.y / 0.866 / state.board.gridWidth);
    pos.x = Math.round((cpos.x - (pos.y * state.board.gridWidth / 2)) / state.board.gridWidth);
    return pos;
}


//按位置计算棋盘位置、大小
function updateSize(state){
    let width = state.canvas.width;
    let height = state.canvas.height; 
    state.board = {}; 
    state.edge = {x:0,y:0};  
    state.ctx.translate(width / 2, height / 2);
    if(width > height){ //横向
        let expw = height / 0.866;
        if(expw <= width){ //y向留空
            state.board.radius = expw / 2;
            state.edge.y = (width - expw) / 2;
        }else{
            state.board.radius = width / 2;
            state.edge.x =  (height / 2 - state.board.radius * 0.866);
        }
        state.ctx.rotate(90 * Math.PI/180);    
        state.edge.width = height;
        state.edge.height = width;  
        state.width = state.canvas.height;
        state.height = state.canvas.width;    
    }else{ //竖向
        let exph = width / 0.866;
        if(exph <= height){ //y向留空
            state.board.radius = exph / 2;
            state.edge.y = (height - exph) / 2;
        }else{
            state.board.radius = height / 2;
            state.edge.x = (width / 2 - state.board.radius * 0.866);
        }
        state.edge.width = width;
        state.edge.height = height;  
        state.width = state.canvas.width;
        state.height = state.canvas.height;       
    }
    state.board.height = 2 * state.board.radius;
    state.board.width = 2 * state.board.radius * 0.866;
    state.board.gridWidth = state.board.width / 14;
    state.pieceRadius = state.board.width / 40;
}



function renderBoard(state){
    let ctx = state.ctx;
    let halfw = state.board.width / 2;
    let halfr = state.board.radius / 2;
    let width = state.board.width;
    let height = state.board.radius * 2;
    /*
    ctx.fillStyle = "#454545"; 
    ctx.strokeStyle = "#000000";
    ctx.beginPath();
    ctx.moveTo(0, 0 - state.board.radius);
    ctx.lineTo(halfw, 0 - halfr);
    ctx.lineTo(halfw, 0 + halfr);
    ctx.lineTo(0, state.board.radius);
    ctx.lineTo(0 - halfw, 0 + halfr);
    ctx.lineTo(0 - halfw, 0 - halfr); 
    ctx.closePath(); 
    ctx.fill();
    ctx.stroke();
*/
    ctx.fillStyle = "#bfbfef";
    ctx.fillRect(0-halfw, 0-state.board.radius, width, height);

    ctx.fillStyle = "#EBCEB2";
    ctx.beginPath();
    ctx.moveTo(0, 0 - state.board.radius);    
    ctx.lineTo(halfw, 0 + halfr);
    ctx.lineTo(0 - halfw, 0 + halfr);
    ctx.closePath(); 
    ctx.fill();
    ctx.beginPath();
    ctx.moveTo(halfw, 0 - halfr);    
    ctx.lineTo(0, state.board.radius);    
    ctx.lineTo(0 - halfw, 0 - halfr);
    ctx.closePath(); 
    ctx.fill();

}


//绘制边缘空白区域
function renderEdge(state){
    let ctx = state.ctx;
    ctx.fillStyle = "#000000";
    let halfw = state.edge.width/2;
    let halfh = state.edge.height/2;
    if(state.edge.x > 0){
        ctx.fillRect(0 - halfw, 0-halfh, state.edge.x, state.edge.height);
        ctx.fillRect(halfw - state.edge.x, 0-halfh, state.edge.x, state.edge.height);
    }
    if(state.edge.y > 0){
        ctx.fillRect(0 - halfw, 0-halfh, state.edge.width ,state.edge.y);
        ctx.fillRect(0 - halfw, halfh - state.edge.y, state.edge.width ,state.edge.y);
    }    
}


//绘制孔(按画布坐标)
function renderHole(ctx, x, y, radius){  
    let r = radius * 0.8;
    let xoff = x + r * 0.1;
    let yoff = y + r * 0.1;    
    let grd1 = ctx.createRadialGradient(xoff,yoff,r*0.9,xoff,yoff,r*1.5);
    grd1.addColorStop(0,"white");
    grd1.addColorStop(1,"black"); 
    ctx.fillStyle = grd1;
    ctx.beginPath();
    ctx.arc(x,y,r,0,2*Math.PI);
    ctx.fill();
}

//绘制棋子经过的孔(按画布坐标)
function renderJumpedHole(ctx, x, y, r, color){
    renderHole(ctx, x, y, r);
    ctx.strokeStyle = color;
    ctx.lineWidth = r * 0.1;
    ctx.beginPath();
    ctx.arc(x,y,r,0,2*Math.PI);
    ctx.stroke();
}

//绘制正常棋子(按画布坐标)
function renderPiece(ctx, x, y, radius, color){
    //主背景 
    let r1 = radius * 0.98;
    ctx.fillStyle = color;
    ctx.shadowBlur = radius * 0.25;
    ctx.shadowColor = "black";    
    ctx.beginPath();
    ctx.arc(x,y,r1,0,2*Math.PI);
    ctx.fill(); 
    ctx.shadowBlur = 0;    
    //高亮效果1
    let xoff = x + radius * 0.1;
    let yoff = y - radius * 0.2;
    let grd1 = ctx.createRadialGradient(xoff,yoff,radius*0.75,xoff,yoff,radius*1.5);
    grd1.addColorStop(0,color);
    grd1.addColorStop(1,"white");   
    ctx.fillStyle = grd1;    
    ctx.beginPath();
    ctx.arc(x,y,radius * 0.95,0,2*Math.PI);
    ctx.fill();
    //高亮效果2
    let r = radius * 0.8;
    ctx.lineWidth = radius * 0.20;
    ctx.strokeStyle = "white"
    ctx.globalAlpha = 0.8;  
    ctx.beginPath();
    ctx.arc(x,y,r,1.7*Math.PI,1.85*Math.PI);
    ctx.stroke(); 
    ctx.beginPath();
    ctx.arc(x,y,r,1.6*Math.PI,1.65*Math.PI);
    ctx.stroke();     
    ctx.globalAlpha = 1;    
}


//绘制选中的棋子(按画布坐标)
function renderPieceSelected(ctx, x, y, r, color){
    //ctx.globalAlpha = 0.6;     
    renderPiece(ctx, x, y, r, color);
    //ctx.globalAlpha = 1;  
    ctx.strokeStyle = color;
    ctx.lineWidth = r * 0.1;
    ctx.beginPath();
    ctx.arc(x,y,r*1.2,0,2*Math.PI);
    ctx.stroke();    

}


//绘制所有棋子
function renderPieces(state){
    forEachBoardPos((x, y) =>{
        if(state.moving && state.moving.piece.x == x && state.moving.piece.y == y){
            return;
        }
        let block = getPieceBlock(state, x, y);
        let pos = posBoardToCanvas(state, x, y);
        if(block){
            if(block.jumped){
                return renderJumpedHole(state.ctx, pos.x, pos.y,state.pieceRadius, block.color);
            }
            if(block.selected){
                return renderPieceSelected(state.ctx, pos.x, pos.y, state.pieceRadius,block.color);
            }
            return renderPiece(state.ctx, pos.x, pos.y, state.pieceRadius,block.color);
        }
        return renderHole(state.ctx, pos.x, pos.y,state.pieceRadius);
    })
}



//指示状态
function renderSign(state){
    let bw = state.board.width;
    let bh = state.board.height;
    let cr = state.pieceRadius * 1.7;
    let x = 0 - bw / 2 + cr;
    let y = 0 - bh / 2 + cr;
    if(state.step == 0)return;
    let tick = Date.now() % 1000;
    if(tick > 500){        
        state.ctx.globalAlpha = 0.5;
    }
    let color = colors[state.step];
    renderPiece(state.ctx, x, y, cr * 0.8, color);    
    state.ctx.globalAlpha = 1;
}

//绘制开始按钮
function renderStartButton(state){
    let r = state.board.width * 0.26;
    let fz = r * 0.7;
    let ctx = state.ctx;
    //外圈    
    ctx.fillStyle = "#f3cd91";
    ctx.shadowBlur = r * 0.04;
    ctx.shadowColor = "black";
    ctx.beginPath();
    ctx.arc(0,0,r,0,2*Math.PI);
    ctx.fill();
    ctx.shadowBlur = 0;
    //文字
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.font = fz + 'px Arial';
    ctx.fillStyle = "#ffffff";
    ctx.fillText("开始", 0, 0);
}

//是否指示标志的位置
function checkSignPos(state, cx, cy){
    let bw = state.board.width;
    let bh = state.board.height;
    let cr = state.pieceRadius * 1.7;
    let x = 0 - bw / 2 + cr;
    let y = 0 - bh / 2 + cr;
    let dx = Math.abs(cx - x);
    let dy = Math.abs(cy - y);
    if(dx < cr && dy < cr)return true;
    return false;
}

//绘制关闭中区域
function renderClosingEdge(state){
    let rc = {};
    let ctx = state.ctx; 
    if(!state.closing)  return; 
    ctx.fillStyle = "#000000";
    let p1 = posWinToCanvas(state, state.closing.src.x, state.closing.src.y);
    let p2 = posWinToCanvas(state, state.closing.x, state.closing.y);
        
    if(state.closing.edge == -1){
        rc.x = 0 - state.board.width / 2;
        if(p2.x <= rc.x)return;
        rc.d = p2.x - rc.x;
        rc.y = 0 - state.board.height / 2 - state.edge.y;
        ctx.fillRect(rc.x, rc.y, rc.d, state.height);
    }else if(state.closing.edge == 1){  
        rc.x = state.board.width / 2;
        if(p2.x >= rc.x)return;
        rc.d = rc.x - p2.x;
        rc.y = 0 - state.board.height / 2 - state.edge.y;
        ctx.fillRect(rc.x - rc.d, rc.y, rc.d, state.height);        
    }else if(state.closing.edge == -2){        
        rc.y = 0 - state.board.height / 2;
        if(p2.y <= rc.y)return;
        rc.d = p2.y - rc.y;
        rc.x = 0 - state.board.width / 2;       
        ctx.fillRect(rc.x, rc.y, state.width, rc.d);        
    }else if(state.closing.edge == 2){        
        rc.y = state.board.height / 2
        if(p2.y >= rc.y)return;
        rc.d = rc.y - p2.y;
        rc.x = 0 - state.board.width / 2;        
        ctx.fillRect(rc.x, rc.y - rc.d, state.width, rc.d);        
    }

}

//全部绘制
function render(state){    
    renderBoard(state);      
    renderPieces(state); 
    renderEdge(state);     
    if(state.step == 0){
        renderStartButton(state);
    }else{
        renderSign(state);
    }
    if(state.moving){        
        let color = colors[state.moving.piece.onwer];
        renderPiece(state.ctx, state.moving.x, state.moving.y, state.pieceRadius, color);
    }
    if(state.closing){
        renderClosingEdge(state);
    }

}

//点击一个棋子时（棋盘坐标）
function onSelectPiece(state, x, y, owner){
    if(state.step == owner){ //当前走子
        state.jumping = {};
        state.jumping.x = x;
        state.jumping.y = y;        
        state.jumping.steps = [];
    }    
    let cpos = posBoardToCanvas(state, x, y);
    state.moving = {};
    state.moving.piece = {};
    state.moving.piece.x = x;
    state.moving.piece.y = y;
    state.moving.piece.onwer = owner;
    state.moving.x = cpos.x;
    state.moving.y = cpos.y;
}



//移动棋子
function movePiece(state, frompos, topos){
    removePiece(state, frompos.x, frompos.y);
    setPieceOwner(state, topos.x, topos.y, state.step);
    checkFinish(state, state.step);
    state.jumping = undefined;
    nextStep(state);
}

//点击一个棋子孔时（棋盘坐标）
function onSelectHole(state, x, y){
    let type = checkBoardPos(x, y);
    if(state.step == 0){ //未开始
        joinPlayer(state, type);
        return;
    }
    if(state.jumping && state.jumping.steps.length){
        let last = state.jumping.steps[state.jumping.steps.length - 1];
        if(last.x == x && last.y == y){ //点击了最后一个孔
            movePiece(state, {x:state.jumping.x,y:state.jumping.y}, last);
            return;
        }
        for (let i = 0; i < state.jumping.steps.length - 1; i++) {
            let pos = state.jumping.steps[i];
            if(pos.x == x && pos.y == y){ //点击了之前跳的路径
                state.jumping.steps.splice(i + 1);
                return;
            }
        }
    }
    if(state.jumping){
        if(canJump(state, x, y)){
            let pos = {x:x,y:y};
            state.jumping.steps.push(pos);
            return;
        }
        if(canMove(state, x, y)){
            let pos = {x:x,y:y};
            state.jumping.steps = [];
            state.jumping.steps.push(pos);
            return;
        }
    }
}

function onMouseDown(state, x, y){    
    let edge = checkEdgePos(state, x, y);
    if(edge){
        state.closing = {};
        state.closing.edge = edge;      
        state.closing.src = {};  
        state.closing.src.x = x;
        state.closing.src.y = y;
        state.closing.x = x;
        state.closing.y = y;
        return;
    } 
    let pos = posWinToBoard(state, x, y);
    let side = checkBoardPos(pos.x, pos.y);
    if(state.step == 0 && side == 7){ //点击了中心位置
        nextStep(state);
        render(state);
        return;
    }
    if(side == 0)return;
    let owner = getPieceOwner(state, pos.x, pos.y);
    if(owner){
        onSelectPiece(state, pos.x, pos.y, owner);
    }else{
        onSelectHole(state, pos.x, pos.y);
    }
    render(state);
}

function onMouseMove(state, x, y){
    let cpos = posWinToCanvas(state, x, y);
    if(state.moving){
        state.moving.x = cpos.x;
        state.moving.y = cpos.y;
        render(state);
        return;
    }
    if(state.closing){
        state.closing.x = cpos.x;
        state.closing.y = cpos.y;
        render(state);
    }    
}


//关闭
function doClose(state){
    reset(state);            
    render(state);
    window.close();
}

function onMouseUp(state, x, y){
    if(state.closing){
        let edge = checkEdgePos(state, x, y);
        if((0 - edge) == state.closing.edge){ //边缘重合
            doClose(state);
            return;
        }
        state.closing = undefined;
        render(state); 
        return;       
    } 
    if(state.moving){ 
        let pos = posWinToBoard(state, x, y);
        let side = checkBoardPos(pos.x, pos.y);
        if(!side){ //移到了棋盘外
            let owner = getPieceOwner(state, state.moving.piece.x, state.moving.piece.y);
            removePlayer(state, owner);            
        }
        state.moving = undefined;      
        render(state); 
        return;  
    }       
}

function setEventListener(state, div){
    let opt = {passive: false};
    
    div.addEventListener('mousedown', (ev)=>{
        onMouseDown(state, ev.x, ev.y);
    });
    div.addEventListener('mouseup', (ev)=>{
        onMouseUp(state, ev.x, ev.y);
    });  
    div.addEventListener('mousemove', (ev)=>{
        onMouseMove(state, ev.x, ev.y);
    }); 
    div.addEventListener('mouseleave', (ev)=>{
        onMouseUp(state, -1, -1);
    });
    div.addEventListener('touchstart', (ev)=>{
        let x = ev.touches[0].pageX;
        let y = ev.touches[0].pageY; 
        onMouseDown(state, x, y); 
        ev.preventDefault();       
    },opt);
    div.addEventListener('touchmove', (ev)=>{
        let x = ev.touches[0].pageX;
        let y = ev.touches[0].pageY; 
        onMouseMove(state, x, y);
        ev.preventDefault();  
    },opt);
    div.addEventListener('touchend', (ev)=>{        
        let x = ev.changedTouches[0].pageX;
        let y = ev.changedTouches[0].pageY;        
        onMouseUp(state, x, y); 
        ev.preventDefault(); 
    },opt);
    div.addEventListener('touchcancel', (ev)=>{
        onMouseUp(state, -1, -1);
        ev.preventDefault(); 
    },opt);    
}



//按body大小创建画布
function createCanvas(){
    let body = container;
    let canvas = document.createElement('canvas'); 
    let rc = body.getBoundingClientRect();
    canvas.width = rc.width;
    canvas.height = rc.height;    
    canvas.style.width = "100%";
    canvas.style.height = "100%";  
    body.innerHTML = '';
    body.appendChild(canvas);
    return canvas;
}

function createState(){
    let state = {};
    state.canvas = createCanvas(); 
    state.ctx = state.canvas.getContext('2d');
    reset(state);
    updateSize(state);    
    render(state);
    setEventListener(state, container);
    setInterval(()=>{
        if(state.step){
            render(state);
        }        
    }, 500);
    return state;
}

function init(){     
    //disableTouchMove(); 
    
    let state = createState();
    window.onresize = function(){
        state.canvas = createCanvas(); 
        state.ctx = state.canvas.getContext('2d');        
        updateSize(state);
        render(state);
    }
}   

</script>
</head>
<body onload="init()">
<div id="container" class="full" ></div>
</body>
</html>
